/**
 * 
 */
package cn.softTank.translator;

import java.util.List;
import java.util.Stack;

import cn.softTank.BcpModel.BcpActivity;
import cn.softTank.BcpModel.BcpAssign;
import cn.softTank.BcpModel.BcpControl;
import cn.softTank.BcpModel.BcpControlType;
import cn.softTank.BpelFactory.BpelFactory;
import cn.softTank.BpelFactory.BpelFactoryImpl;
import cn.softTank.BpelModel.Assign;
import cn.softTank.BpelModel.Copy;
import cn.softTank.BpelModel.From;
import cn.softTank.BpelModel.Link;
import cn.softTank.BpelModel.Links;
import cn.softTank.BpelModel.Source;
import cn.softTank.BpelModel.Targets;
import cn.softTank.BpelModel.To;

/**
 * @author Yuzone (smartzxy@gmail.com)
 * 
 */
public class ControlActivity {

	private BcpControl control;
	private Assign assign;
	private BpelFactory bpelFactory;
	private int count;
	private Stack<Source> sourceStack = new Stack<Source>();
	private Stack<Targets> targetsStack = new Stack<Targets>();

	public ControlActivity(BcpControl control, Links links, Counter value) {
		super();
		this.control = control;
		parser(links, value);
	}

	public ControlActivity() {
	}

	public BcpControl getControl() {
		return control;
	}

	public void setControl(BcpControl control) {
		this.control = control;
	}

	public BpelFactory getBpelFactory() {
		return bpelFactory;
	}

	public void setBpelFactory(BpelFactory bpelFactory) {
		this.bpelFactory = bpelFactory;
	}

	public int getType() {
		if (control != null)
			return control.getType();
		return -1;
	}

	public void setType(int type) {
		if (control != null) {
			control.setType(type);
		}
	}

	public Assign getAssign() {
		return assign;
	}

	public void setAssign(Assign assign) {
		this.assign = assign;
	}

	public List<BcpActivity> getSuperiors() {
		if (control != null)
			return control.getSuperiors();
		return null;
	}

	public void setSuperiors(List<BcpActivity> superiors) {
		if (control != null) {
			control.setSuperiors(superiors);
		}
	}

	public List<BcpActivity> getInferiors() {
		if (control != null)
			return control.getInferiors();
		return null;
	}

	public void setInferiors(List<BcpActivity> inferiors) {
		if (control != null) {
			control.setInferiors(inferiors);
		}
	}

	public String getName() {
		return control.getName();
	}

	public void setName(String name) {
		control.setName(name);
	}

	public int getCount() {
		if (control != null) {
			switch (getType()) {
			case BcpControlType.AND_JOIN:
			case BcpControlType.OR_JOIN:
			case BcpControlType.XOR_JOIN:
				count = control.getSuperiors().size();
				break;
			case BcpControlType.AND_SPLIT:
			case BcpControlType.OR_SPLIT:
			case BcpControlType.XOR_SPLIT:
				count = control.getInferiors().size();
				break;
			default:
			}
		}
		return count;
	}

	public ControlActivity parser(Links links, Counter count) {

		if (control != null) {
			this.assign = createAssign(links, count);

			switch (getType()) {
			case BcpControlType.AND_JOIN:
				createAJ(links, count);
				break;
			case BcpControlType.OR_JOIN:
				createOJ(links, count);
				break;
			case BcpControlType.XOR_JOIN:
				break;
			case BcpControlType.AND_SPLIT:
				createAS(links, count);
				break;
			case BcpControlType.OR_SPLIT:
				break;
			case BcpControlType.XOR_SPLIT:
				break;
			case BcpControlType.SEQUENCE:
				createSequ(links, count);
				break;
			default:
			}
		}
		return this;
	}

	public Targets popTargets() {
		return targetsStack.pop();
	}

	public Source popSource() {
		return sourceStack.pop();
	}

	private Assign createAssign(Links links, Counter count) {
		if (bpelFactory == null) {
			bpelFactory = new BpelFactoryImpl();
		}

		Assign assign = bpelFactory.createAssign();
		if (control.getAssignList() != null) {
			List<BcpAssign> copyList = control.getAssignList();
			for (BcpAssign ba : copyList) {
				Copy copy = bpelFactory.createCopy();
				From from = bpelFactory.createFrom();
				// if (ba.getFrom().startsWith("$")) {
				from.setLiteral(ba.getFrom());
				// } else {
				// from.setLiteral("<literal>" + ba.getFrom() + "</literal>");
				// }
				copy.setFrom(from);
				To to = bpelFactory.createTo();
				// if (ba.getTowards().startsWith("$")) {
				to.setLiteral(ba.getTowards());
				// } else {
				// to.setLiteral("<literal>" + ba.getTowards() + "</literal>");
				// }
				to.setLiteral(ba.getTowards());
				copy.setTo(to);
				assign.addCopy(copy);
			}
		}
		assign.setSources(bpelFactory.createSources());

		return assign;
	}

	private void createAS(Links links, Counter count) {
		for (int i = 0; i < getCount(); i++) {
			Link link = bpelFactory.createLink("link" + count.getCount());
			links.addLink(link);
			Source s = bpelFactory.createSource(link);
			assign.getSources().addSource(s);
			// sourceStack.push(s);
			Targets ts = bpelFactory.createTargets();
			ts.addTarget(bpelFactory.createTarget(link));
			targetsStack.push(ts);
			count.increase();
		}
		Link link = bpelFactory.createLink("link" + count.getCount());
		links.addLink(link);
		Source s = bpelFactory.createSource(link);
		sourceStack.push(s);
		Targets ts = bpelFactory.createTargets();
		ts.addTarget(bpelFactory.createTarget(link));
		assign.setTargets(ts);
		count.increase();
	}

	private void createAJ(Links links, Counter count) {
		Targets ts = bpelFactory.createTargets();
		String expr = "";
		for (int i = 0; i < getCount(); i++) {
			Link link = bpelFactory.createLink("link" + count.getCount());
			links.addLink(link);
			Source s = bpelFactory.createSource(link);
			sourceStack.push(s);
			if (i != 0) {
				expr += " and ";
			}
			expr += "$link" + count.getCount();
			ts.addTarget(bpelFactory.createTarget(link));
			count.increase();
		}
		ts.setJoinCondition(bpelFactory.createJoinCondition(expr));
		assign.setTargets(ts);
		Link link = bpelFactory.createLink("link" + count.getCount());
		links.addLink(link);
		Source s = bpelFactory.createSource(link);
		assign.getSources().addSource(s);
		Targets ts2 = bpelFactory.createTargets();
		ts2.addTarget(bpelFactory.createTarget(link));
		targetsStack.push(ts2);
		count.increase();
	}

	private void createOJ(Links links, Counter count) {
		Targets ts = bpelFactory.createTargets();
		String expr = "";
		for (int i = 0; i < getCount(); i++) {
			Link link = bpelFactory.createLink("link" + count.getCount());
			links.addLink(link);
			Source s = bpelFactory.createSource(link);
			sourceStack.push(s);
			if (i != 0) {
				expr += " or ";
			}
			expr += "$link" + count.getCount();
			ts.addTarget(bpelFactory.createTarget(link));
			count.increase();
		}
		ts.setJoinCondition(bpelFactory.createJoinCondition(expr));
		assign.setTargets(ts);
		Link link = bpelFactory.createLink("link" + count.getCount());
		links.addLink(link);
		Source s = bpelFactory.createSource(link);
		assign.getSources().addSource(s);
		Targets ts2 = bpelFactory.createTargets();
		ts2.addTarget(bpelFactory.createTarget(link));
		targetsStack.push(ts2);
		count.increase();
	}

	private void createSequ(Links links, Counter count) {
		Link link = bpelFactory.createLink("link" + count.getCount());
		count.increase();
		links.addLink(link);
		// source for superior
		sourceStack.push(bpelFactory.createSource(link));
		// targets for assign
		Targets ts = bpelFactory.createTargets();
		ts.addTarget(bpelFactory.createTarget(link));
		assign.setTargets(ts);
		// new Link
		link = bpelFactory.createLink("link" + count.getCount());
		count.increase();
		links.addLink(link);
		// source for assign
		assign.getSources().addSource(bpelFactory.createSource(link));
		// targets for inferior
		ts = bpelFactory.createTargets();
		ts.addTarget(bpelFactory.createTarget(link));
		targetsStack.push(ts);
	}
}
